export const deepClone = (source, target) => {
  if (target === undefined) {
    switch (true) {
      case source instanceof Array:
        target = new source.constructor();
        break;
      case source instanceof HTMLElement:
        target = source.cloneNode(true);
        break;
      case source instanceof Date:
      case source instanceof RegExp:
      case source.constructor.__proto__.name === "TypedArray":
      case source instanceof Map:
      case source instanceof Set:
        target = new source.constructor(source);
        break;
      case typeof source === "function":
        var arr = source.toString().replace(/\n/g, "").match(/\((.*?)\)\s*\{(.*)\}/).slice(1);
        target = new Function(arr[0], arr[1]);
        break;
      default:
        target = {}
    }
  }
  // 获取对象的所有属性名，包括不可枚举和Symbol，形成一个数组
  var keys = Reflect.ownKeys(source);
  for (var i = 0; i < keys.length; i++) {
    // 获取每个属性的描述对象
    var desc = Object.getOwnPropertyDescriptor(source, keys[i]);
    //    判断这个属性是不是对象，如果是对象，并且不是null
    //    if(typeof desc.value==="object" && desc.value!==null){
    if (desc.value instanceof Object) {
      // 如果当前的属性是constructor跳出不复制，复制会造成堆栈上限溢出
      if (keys[i] === "constructor") {
        continue;
      }
      //    这里完成复制这个对象
      Object.defineProperty(target, keys[i], {
        enumerable: desc.enumerable,
        configurable: desc.configurable,
        writable: desc.writable,
        // 递归获取复制新的对象赋值给value
        value: deepClone(desc.value)
      })
      // 如果当前属性时prototype时，在当前prototype属性下新增一个constructor属性是当前构造函数
      if (keys[i] === "prototype") {
        Object.defineProperty(target.prototype, "constructor", {
          value: target
        })
      }
    } else {
      // 如果这个描述对象的值不是引用类型，直接将这个属性的描述对象设置给新的目标对象中
      Object.defineProperty(target, keys[i], desc);
    }
  }
  return target;
}

export const delay = (ms = 1000) => {
  return new Promise(_ => {
    setTimeout(() => {
      _()
    }, ms);
  })
}